#pragma once

#include "WizardState.h"

#define CARD_SIZE_OF_DECK	WizardCard::count()
#define MEMORY_SIZE_OF_DECK	sizeof(CardPointer) * CARD_SIZE_OF_DECK

class WizardTrickState :
	public WizardState
{
public:
	static
	int
	const			FLAT_BID_REWARD = 20,
					PER_BID_REWARD = 10,
					PER_BID_PENALTY = 10;

					WizardTrickState() :
						WizardState()
					{
						hands = new CardPointer[CARD_SIZE_OF_DECK];
					} // end constructor

	virtual
	GamePlayer*		getActivePlayer();

	virtual
	WizardDeck		getDeck() {
						return hands;
					} // end method

	virtual
	GameState*		getNextSequence();

	virtual
	StateList&		listAvailableActions()
	{
		if (actions)
			return *actions;

		actions = new StateList();

		auto playCount =	countCardsPlayed() + 1;
		auto trickCount =	getTrickNumber();
		auto leader =		getLeader();

		// Sometimes, the set of child nodes collectively represent the start of a new trick.
		if (playCount % playerCount == 0)
			if (trickCount == roundNumber)
				// This means that the last card of the round was played during this node,
				// and the consequence is that there are no actions to take from here.
				return *actions;
			else
				// The leader of the next trick becomes the person who won this trick.
				leader = determineWinner(trickCount, leader, hands);

		{ // start block: assembly of child nodes into a list
			auto childPrefix =	(playCount << ENCODE_PLAYS) + (leader << ENCODE_LEADER);
			auto myPlayer =		getActiveSeat();

			for (auto i = 0; i != roundNumber; ++i)
			{
				auto child = initialize(childPrefix + (i << ENCODE_CHOICE), hands);
				child->playCard(myPlayer, trickCount, i);
				actions->push_back(child);
			} // end loop: each child
		} // end block: assembly of child nodes into a list

		return *actions;
	} // end GameState method

	virtual
	ExpectedValue	score(SeatNumber);

	virtual
	void			transitionFrom(GameState*);

protected:
	WizardDeck		hands;

					~WizardTrickState()
					{
						delete[] hands;
					} // end destructor

	/*
		Retrieve a WizardTrickState and overwrite any obsolete information it has
		with the parent node's deck permutation and NULL values everywhere else.
	*/
	static
	WizardTrickState*	initialize(
						const NodeIndex		nodeIndex,
						const WizardDeck	hands = deck
					) {
						// TODO: Institute object pool.
						//if (result->actions)
							//delete result->actions;

						WizardTrickState* result = new WizardTrickState();

						memcpy(result->hands, hands, MEMORY_SIZE_OF_DECK);
						result->actions = NULL;
						result->nodeIndex = nodeIndex;

						return result;
					} // end class method
}; // end class
